#include "ads1299x.h"

// #include "esp_log.h"

// static const char *TAG = "m_ads";

uint8_t tx[3]={0};
uint8_t rx[3]={0};

uint8_t REG_CHnSET[8]={ADS1299_CH1SET_REG,ADS1299_CH2SET_REG,ADS1299_CH3SET_REG,ADS1299_CH4SET_REG,
    ADS1299_CH5SET_REG,ADS1299_CH6SET_REG,ADS1299_CH7SET_REG,ADS1299_CH8SET_REG};

/**
 * @brief chip select ADS1299 by pull low of its cs pin
 *
 * @warning None.
 *
 * @param  p_ads pointer of the specific ads1299_t instance;
 *
 * @return
 *     - None
 */
static void chip_select(ads1299_t * p_ads){
    if(p_ads->CS_PIN==PIN_NOT_USE) return;
    p_ads->pin_low(p_ads->CS_PIN);
}

/**
 * @brief chip unselect ADS1299 by pull high of its cs pin
 *
 * @warning None.
 *
 * @param  p_ads pointer of the specific ads1299_t instance;
 *
 * @return
 *     - None
 */
static void chip_unselect(ads1299_t * p_ads){
    if(p_ads->CS_PIN==PIN_NOT_USE) return;
    p_ads->pin_high(p_ads->CS_PIN);
}

/**
 * @brief  read ADS1299 certain register
 *
 * @warning None.
 *
 * @param  p_ads pointer of the specific ads1299_t instance;
 * @param  address the address of ADS1299 Register you are requesting;
 * @param  value the value you are want to write in;
 * 
 * @return 
 *      - the result of spi transfer.
 */
static int WRITE_ONE_REG(ads1299_t * p_ads,uint8_t address, uint8_t value){
    chip_select(p_ads);
    tx[0]=address | ADS1299_WRITE_REG_CMD; //  RREG expects 001rrrrr where rrrrr = address
    tx[1]=0x00;
    tx[2]=value;
    int r = p_ads->xfer(tx,rx,3);
    chip_unselect(p_ads);
    return r;
} 

/**
 * @brief  read ADS1299 certain register
 *
 * @warning None.
 *
 * @param  p_ads pointer of the specific ads1299_t instance;
 * @param  address the address of ADS1299 Register you are requesting;
 * @param  *out the value read from reg;
 *
 * @return 
 *      - the result of spi transfer.
 */
static int READ_ONE_REG(ads1299_t * p_ads,uint8_t address, uint8_t *out){
    chip_select(p_ads);
    tx[0]=address | ADS1299_READ_REG_CMD; //  RREG expects 001rrrrr where rrrrr = address
    tx[1]=0x00;
    tx[2]=0x00;
    int r = p_ads->xfer(tx,rx,3);
    chip_unselect(p_ads);
    *out = rx[2];
    return r;
}

/**
 * @brief  send a one byte CMD to ADS1299 
 *
 * @warning None.
 *
 * @param  p_ads pointer of the specific ads1299_t instance;
 * @param  cmd the cmd of you send to ADS1299;
 *
 * @return 
 *      - the result of spi transfer.
*/
static int SEND_CMD(ads1299_t * p_ads,uint8_t cmd){
    chip_select(p_ads);
    tx[0]=cmd;
    int r = p_ads->xfer(tx,rx,1);
    chip_unselect(p_ads);
    return r;
}

static void parse_id_reg(ads1299_t * p_ads, uint8_t regVal){
    p_ads->id.revId = (regVal & 0x10) >> 4;
    p_ads->id.devId = (regVal & 0x0C) >> 2;
    p_ads->id.nuCh  = (regVal & 0x03);

    // 2:8channels, 1:6channels, 0:4channels     
    if(p_ads->id.nuCh==2) p_ads->CH_NUM = 8;
    if(p_ads->id.nuCh==1) p_ads->CH_NUM = 6;
    if(p_ads->id.nuCh==0) p_ads->CH_NUM = 4;
}

void ads1299_get_id(ads1299_t * p_ads){
    SEND_CMD(p_ads,ADS1299_SDATAC_CMD);
    uint8_t regVal = 0;
    READ_ONE_REG(p_ads,ADS1299_ID_REG,&regVal);
    parse_id_reg(p_ads,regVal);
}

void ads1299_init_hardware(ads1299_t * p_ads){
    p_ads->hardware_config();
}

void ads_start_by_start_pin(ads1299_t * p_ads){
    p_ads->pin_high(p_ads->START_PIN);
}


void ads1299_setup(ads1299_t * p_ads){

    SEND_CMD(p_ads,ADS1299_RESET_CMD);
    p_ads->delay_ms(10);

    SEND_CMD(p_ads,ADS1299_SDATAC_CMD);
    p_ads->delay_ms(10);

    ads1299_get_id(p_ads);//get the channel number and set to the object
    p_ads->delay_ms(10);

    WRITE_ONE_REG(p_ads,ADS1299_CONFIG1_REG, 0xF6); 
    //0xF6:1111 0110 : Multiple readback mode, Oscillator clock output enabled, 250SPS
    p_ads->delay_ms(1);

    // WRITE_ONE_REG(p_ads,CONFIG2, 0xD5); 
    // //0xD0:1101 0000 : Test signals are generated internally
    // //0xD5:1101 0101 : Test signals are generated internally, 2 × –(VREFP – VREFN) / 2400, Pulsed at fCLK / (2^20)

    if(p_ads->BIAS_BUFFER){
        WRITE_ONE_REG(p_ads,ADS1299_CONFIG3_REG, 0xEC); 
    }else{
        WRITE_ONE_REG(p_ads,ADS1299_CONFIG3_REG, 0xE0); 
    }
    //0xEC:1110 1100 : 
    //Enable internal reference buffer
    //BIASREF signal (AVDD + AVSS) / 2 generated internally
    //BIAS buffer is enabled

    //0xEC:1110 1100 : 
    //Enable internal reference buffer
    //BIASREF signal fed externally
    //BIAS buffer is powered down
    p_ads->delay_ms(1);

    for(int ch=0;ch<p_ads->CH_NUM;ch++){
        WRITE_ONE_REG(p_ads,REG_CHnSET[ch], 0x40);  
        p_ads->delay_ms(1);    
    }
    //0x40:0100 0000 : PGA gain=8;Normal electrode input
    //0x45:0100 0101 : PGA gain=8;Test signal

    WRITE_ONE_REG(p_ads,ADS1299_BIAS_SENSP_REG, 0xFF);      
    p_ads->delay_ms(1);

    WRITE_ONE_REG(p_ads,ADS1299_BIAS_SENSN_REG, 0xFF);      
    p_ads->delay_ms(1);
    //0xFF: connect all inputs to BIAS    

    WRITE_ONE_REG(p_ads,ADS1299_MISC1_REG, 0x20);      
    //0x20: SRB1 Switches closed
    p_ads->delay_ms(1);
    
    SEND_CMD(p_ads,ADS1299_RDATAC_CMD);
    p_ads->delay_ms(1);   
}

uint8_t tx_buff_27_byte[DATA_PACKAGE_LEN]={0};
// make sure the rx buff longer than 27 bytes
// use this in RDATAC mode
void ads1299_get_data(ads1299_t * p_ads,uint8_t * rx){
    p_ads->xfer(tx_buff_27_byte,rx,DATA_PACKAGE_LEN);
}




